﻿using System;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using SdmxMl.Structure;
using SdmxMl.Panels;
using SdmxMl.Common;

namespace SdmxMl.UC
{
    /// <summary> DSD internal view </summary>
    public partial class UcKeyFamilyGrid : UserControl, IUrnSelect
    {
        #region Internal Members

        private PanelAnnotationList pannelAnnot;
        private BaseDimensionTypeList bdList;
        private BaseDimensionType rowBd;
        private BindingManagerBase bm = null;
        private bool inBinding;
        private bool _isFinal;
        private int imageColIndex = 1;

        #endregion

        #region C'tor

        public UcKeyFamilyGrid()
        {
            InitializeComponent();
        }
        #endregion

        #region Bind item

        public bool BindFromNode(TreeNode node, PanelAnnotationList panelAnnotation, bool isf)
        {
            _isFinal = isf;
            pannelAnnot = panelAnnotation;
            bdList = null; 
            if (node != null)
                bdList = node.Tag as BaseDimensionTypeList;
            BindToControls();

            return Visible;
        }

        private void BindToControls()
        {
            if (bdList != null)
            {
                inBinding = true;

                // A column for attachement level is used only for Attributes
                Visible = true;

                DataTable tb = bdList.GetTableRepresentation();

                // Previous editing in grid contained same object ?
                if (bdList.Contains(rowBd) == false)
                    rowBd = null;

                dataGridView.DataSource = tb;
                if (rowBd != null)
                    SelectGridRow(dataGridView, bdList.IndexOf(rowBd));
                ucEditDimension.BindFromList(bdList, dataGridView, rowBd, _isFinal);

                ucEditDimension.Visible = tb.Rows.Count > 0;
                EnableGrigButtons(true);
                inBinding = false;

                dataGridView_SelectionChanged(this, EventArgs.Empty);

            }
            else
                Visible = false;
        }
        #endregion

        #region Update item & Node content from detail View
        
        protected bool BindFromControls()
        {
            bool err = false;
            if (bdList != null)
            {
                ucEditDimension.UpdateRow();
            }
            return err;
        }

        public bool UpdateNodeTag(TreeNode node)
        {
            if (node != null)
                BindFromControls();

            return false; // true on error
        }
        #endregion

        #region Datagrid

        /// <summary>Update Grid buttons state</summary>
        /// <param name="enable">If true buttons are enabled</param>
        protected void EnableGrigButtons(bool enable)
        {
            CrossSectionalMeasureTypeList csml = bdList as CrossSectionalMeasureTypeList;
            butAdd.Enabled = enable;

            DimensionTypeList dtl = bdList as DimensionTypeList;
            butCreateTimeDim.Visible = dtl != null && dtl.GetTimeDimension() == null;

            butEdit.Enabled = false;
            int miniCount = csml != null ? 1 : 0;
            butRemove.Enabled = enable && bdList != null && (bdList.Count > miniCount) && dataGridView.SelectedCells.Count > 0;

            // No change possible for final artefact
            if (_isFinal)
            {
                butAdd.Enabled = false;
                butRemove.Enabled = false;
                butCreateTimeDim.Visible = false;
            }

        }
/*
        void UcBaseDim_IndexChanged(object sender, EventArgs e)
        {
            int ind = (int)sender;
            SelectGridRow(dataGridView, ind);

        }
*/

        private void dataGridView_SelectionChanged(object sender, EventArgs e)
        {
            if (inBinding)
                return;

           // dataGridView.so = SortOrder.None;
            ucEditDimension.UpdateRow();
            bm = dataGridView.BindingContext[dataGridView.DataSource, dataGridView.DataMember];
            if (bm.Count > 0)
            {
                DataRow findRow = ((DataRowView)bm.Current).Row;
                if (findRow != null)
                {
                    int index = (dataGridView.DataSource as DataTable).Rows.IndexOf(findRow);
                    rowBd = null;
                    if (index >= 0 && index < bdList.Count)
                    {
                        rowBd = bdList[index];
                        pannelAnnot.BindFromNode(rowBd, _isFinal);
                        ucEditDimension.BindRow(rowBd);
                    }
                }
            }
             
        }


        private void UnsortDataGrid(DataGridView dgv,  DataTable tb)
        {
            if (dgv.SortedColumn != null)
            {
                int index = -1;
                bm = dgv.BindingContext[dgv.DataSource, dgv.DataMember];
                DataRow findRow = ((DataRowView)bm.Current).Row;
                if (findRow != null)
                {
                    index = (dgv.DataSource as DataTable).Rows.IndexOf(findRow);
                    dgv.DataSource = tb;
                    SelectGridRow(dgv, index);
                }
            }
       }

        private void SelectGridRow(DataGridView dgv, int index)
        {
            if (index < 0)
                return;

            if (dgv.CurrentCell != null)
                dgv.CurrentCell.Selected = false;
            dgv.Rows[index].Cells[0].Selected = true;
            dgv.CurrentCell = dgv.SelectedCells[0];

        }

        private Rectangle dragBoxFromMouseDown;
        private int rowIndexFromMouseDown;
        private int rowIndexOfItemUnderMouseToDrop;

        private void dataGridView_MouseMove(object sender, MouseEventArgs e)
        {
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
            {
                // If the mouse moves outside the rectangle, start the drag.
                if (dragBoxFromMouseDown != Rectangle.Empty &&
                !dragBoxFromMouseDown.Contains(e.X, e.Y))
                {
                    // Proceed with the drag and drop, passing in the list item.                    
                    DragDropEffects dropEffect = dataGridView.DoDragDrop(
                    dataGridView.Rows[rowIndexFromMouseDown],
                    DragDropEffects.Move);
                }
            }
        }

        private void dataGridView_MouseDown(object sender, MouseEventArgs e)
        {
            // Get the index of the item the mouse is below.
            rowIndexFromMouseDown = dataGridView.HitTest(e.X, e.Y).RowIndex;
            if (rowIndexFromMouseDown != -1)
            {
                // Remember the point where the mouse down occurred. 
                // The DragSize indicates the size that the mouse can move 
                // before a drag event should be started.                
                Size dragSize = SystemInformation.DragSize;
                // Create a rectangle using the DragSize, with the mouse position being
                // at the center of the rectangle.
                dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
                e.Y - (dragSize.Height / 2)),
                dragSize);
            }
            else
                // Reset the rectangle if the mouse is not over an item in the ListBox.
                dragBoxFromMouseDown = Rectangle.Empty;
        }

        private void dataGridView_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;

            //manage to scroll if needed
            if (e.Y <= PointToScreen(new Point(dataGridView.Location.X, dataGridView.Location.Y)).Y + 40 &&
                dataGridView.FirstDisplayedScrollingRowIndex > 0)
                dataGridView.FirstDisplayedScrollingRowIndex -= 1;
            
            if (e.Y >= PointToScreen(new Point(dataGridView.Location.X +
               dataGridView.Width, dataGridView.Location.Y +
               dataGridView.Height)).Y - 10)
                dataGridView.FirstDisplayedScrollingRowIndex += 1;


        }

        private void dataGridView_DragDrop(object sender, DragEventArgs e)
        {
            // The mouse locations are relative to the screen, so they must be 
            // converted to client coordinates.
            Point clientPoint = dataGridView.PointToClient(new Point(e.X, e.Y));
            // Get the row index of the item the mouse is below. 
            rowIndexOfItemUnderMouseToDrop =
            dataGridView.HitTest(clientPoint.X, clientPoint.Y).RowIndex;
            // If the drag operation was a move then remove and insert the row.
            if (e.Effect == DragDropEffects.Move)
            {
                if (rowIndexOfItemUnderMouseToDrop >= bdList.Count || rowIndexOfItemUnderMouseToDrop < 0)
                    return;

                DataGridViewRow rowToMove = e.Data.GetData(typeof(DataGridViewRow)) as DataGridViewRow;
                BaseDimensionType item = bdList[rowIndexFromMouseDown];
                DataTable tb = dataGridView.DataSource as DataTable;
                DataRow row = tb.Rows[rowIndexFromMouseDown];
                object[] ob = tb.Rows[rowIndexFromMouseDown].ItemArray;
                object[] ob2 = tb.Rows[rowIndexOfItemUnderMouseToDrop].ItemArray;
                tb.Rows[rowIndexFromMouseDown].ItemArray = ob2;
                tb.Rows[rowIndexOfItemUnderMouseToDrop].ItemArray = ob;

             //   tb.Rows.InsertAt(row, rowIndexOfItemUnderMouseToDrop);

                bdList.RemoveAt(rowIndexFromMouseDown);
                bdList.Insert(rowIndexOfItemUnderMouseToDrop, item);
                dataGridView.DataSource = bdList.GetTableRepresentation();
                SelectGridRow(dataGridView, rowIndexOfItemUnderMouseToDrop);
                dataGridView_SelectionChanged(this, EventArgs.Empty);
            }
        }

        private bool inCompletion;
        private void dataGridView_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            if (inCompletion == false)
            {
                inCompletion = true;

                for (int i = 0; i < this.dataGridView.Rows.Count; i++)
                {
                    if (dataGridView.Rows[i].Cells[imageColIndex].Value == System.DBNull.Value)
                    {
                        if (bdList is AttributeTypeList)
                        {
                            int img = (int)((AttributeType.AttributeKindType)dataGridView.Rows[i].Cells[imageColIndex + 1].Value);
                            dataGridView.Rows[i].Cells[imageColIndex].Value = imageListAttrib.Images[img];
                        }

                        else
                        {
                            int img = (int)((DimensionType.DimensionKind)dataGridView.Rows[i].Cells[imageColIndex + 1].Value);
                            dataGridView.Rows[i].Cells[imageColIndex].Value = imageList1.Images[img];
                        }
                    }
                }

                dataGridView.Columns[ColMeasure.Name].Visible = false; // bdList is CrossSectionalMeasureTypeList;
                dataGridView.Columns[colCross.Name].Visible = (bdList is CrossSectionalMeasureTypeList) == false;
                dataGridView.Columns[colCode.Name].Visible = false; // bdList is CrossSectionalMeasureTypeList;
                dataGridView.Columns[colAttachLevel.Name].Visible = bdList is AttributeTypeList;
                dataGridView.Columns[ColAssign.Name].Visible = bdList is AttributeTypeList;
                labelRowCount.Text = dataGridView.RowCount.ToString();

                inCompletion = false;
            }
        }
        #endregion //Datagrid

        #region Buttons Events

        /// <summary> Add a variable </summary>
        /// <param name="sender"></param> <param name="e"></param>
        private void butAdd_Click(object sender, EventArgs e)
        {
            
            CrossSectionalMeasureTypeList csml = bdList as CrossSectionalMeasureTypeList;
            if (csml != null)
            {
                /*
                if (csml.CreatefromMeasureCodelist())
                {
                    if (ucEditDimension.Visible == false)
                        ucEditDimension.Visible = true;
                    dataGridView.DataSource = bdList.GetTableRepresentation();
                    dataGridView.FirstDisplayedScrollingRowIndex = 0;
                    SelectGridRow(dataGridView, 0);
                }
                else */
                {
                    if (csml.ParentDsd == null || csml.ParentDsd.DimensionList.GetMeasureDimensions().Count == 0)
                    {
                        MessageBox.Show("Unable to initialize CSM, No measure defined in dimension!", "CSM", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }
            }
            
            {
                if (ucEditDimension.Visible == false)
                    ucEditDimension.Visible = true;
                // Special case if Create TimeDim button call
                BaseDimensionType bdim = (sender == butCreateTimeDim) ? new TimeDimensionType() : bdList.NewItem();
                bdList.Add(bdim);
                dataGridView.DataSource = bdList.GetTableRepresentation();
                dataGridView.FirstDisplayedScrollingRowIndex = bdList.Count - 1;
                SelectGridRow(dataGridView, bdList.Count - 1);
            }

            dataGridView_SelectionChanged(this, EventArgs.Empty);
            EnableGrigButtons(true);

        }

        private void butRemove_Click(object sender, EventArgs e)
        {
            bm = dataGridView.BindingContext[dataGridView.DataSource, dataGridView.DataMember];
            if (bm.Count > 0)
            {
                DataRow findRow = ((DataRowView)bm.Current).Row;
                if (findRow != null)
                {
                    int index = (dataGridView.DataSource as DataTable).Rows.IndexOf(findRow);
                    BaseDimensionType bd = null;
                    if (index >= 0 && index < bdList.Count)
                    {
                        bd = bdList[index];
                    }

                    // Primary measure cannot be deleted
                    CrossSectionalMeasureTypeList csml = bdList as CrossSectionalMeasureTypeList;
                    if (csml != null && bd == csml.PrimaryMeasure)
                    {
                        MessageBox.Show(this, "Cannot erase primary measure.", "Caution");
                    }
                    else
                    {
                        bdList.RemoveAt(index);
                        dataGridView.DataSource = bdList.GetTableRepresentation();
                        index = Math.Min(bdList.Count - 1, index);
                    }
                    SelectGridRow(dataGridView, index);
                    EnableGrigButtons(true);
                }
                if (bdList.Count == 0)
                    ucEditDimension.Visible = false;
                else
                    dataGridView_SelectionChanged(this, EventArgs.Empty);


            }
        }
        #endregion

        #region Datagrid Tooltip

        private void dataGridView_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == imageColIndex)
                ToolTip(e, true);
        }

        private void ToolTip(DataGridViewCellEventArgs e, bool showTip)
        {
            try
            {
                if (e.RowIndex >= 0 && e.RowIndex < dataGridView.Rows.Count)
                {

                    DataGridViewImageCell cell = (DataGridViewImageCell)
                        dataGridView.Rows[e.RowIndex].Cells[imageColIndex];
                    DataGridViewImageColumn imageColumn =
                        (DataGridViewImageColumn)dataGridView.Columns[imageColIndex];

                    if (showTip)
                    {
                        if (bdList is AttributeTypeList)
                            cell.ToolTipText = ((AttributeType.AttributeKindType)dataGridView.Rows[e.RowIndex].Cells[imageColIndex + 1].Value).ToString();
                        else if (bdList is DimensionTypeList)
                            cell.ToolTipText = ((DimensionType.DimensionKind)dataGridView.Rows[e.RowIndex].Cells[imageColIndex + 1].Value).ToString();
                    }
                    else
                    {
                        cell.ToolTipText = String.Empty;
                    }
                }
            }
            catch { }
        }

        private void dataGridView_CellMouseLeave(object sender,
            DataGridViewCellEventArgs e)
        {
            ToolTip(e, false);
        }
        #endregion

        #region IUrnSelect Members

        public void SelectItem(UrnParser up)
        {
            if (up != null && up.ArType == SdmxMl.Manager.SdmxArtefactType.KeyFamilies &&
                dataGridView.DataSource != null)
            {
                // Try to locate refered concept name
                foreach (BaseDimensionType bdt in bdList)
                    if (bdt.ConceptInfo.Id == up.SubTypeId)
                    {
                        rowBd = bdt;
                        BindToControls();

                        /*
                        pannelAnnot.BindFromNode(rowBd, _isFinal);
                        ucEditDimension.BindRow(rowBd);
                        SelectGridRow(dataGridView, bdList.IndexOf(bdt));
                        */
                        break;
                    }
                
            }
        }

        #endregion

    }
}
